#ifndef SYSYF_CONSTPROPAGATION_H
#define SYSYF_CONSTPROPAGATION_H
#include "Pass.h"
#include "Constant.h"
#include "Instruction.h"
#include "Module.h"
#include "Value.h"
#include "IRStmtBuilder.h"
#include "BasicBlock.h"


// 用来判断value是否为ConstantFloat/ConstantInt
ConstantInt *cast_to_const_int(Value *value);
ConstantFloat *cast_to_const_float(Value *value);

class ConstFolder
{
public:
    ConstFolder(Module *module) : module_(module) {}

    ConstantInt *compute(Instruction::OpID op, ConstantInt *value1, ConstantInt *value2);
    ConstantFloat *compute(Instruction::OpID op, ConstantFloat *value1,ConstantFloat *value2);
    ConstantInt *compute(CmpInst::CmpOp op, ConstantFloat *value1, ConstantFloat *value2);
    ConstantInt *compute(CmpInst::CmpOp op,ConstantInt *value1,ConstantInt *value2);
    ConstantInt *compute_zext(Instruction::OpID op, ConstantInt *value);

    // ...
private:
    Module *module_;
};

class ConstPropagation : public Pass
{
private:
    const std::string name = "ConstPropagation";
    ConstFolder * folder;
    BasicBlock* bb;
    IRStmtBuilder* builder;
    Function* _func;
    Type *INT_1,*INT_32,*FLOAT;

    
public:
    ConstPropagation(Module *module) : Pass(module) {
        builder = new IRStmtBuilder(nullptr,module);
        folder = new ConstFolder(module);
    }
    void execute() final;
    const std::string get_name() const override {return name;}
    void Const_Propagation(BasicBlock* bb);
    void cond_opt();
    void const_opt();
    void set_globalVar();
    void delete_trans();
};

#endif  // SYSYF_CONSTPROPAGATION_H